package com.wuzhipeng.heart.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wuzhipeng.heart.user.config.UserContext;
import com.wuzhipeng.heart.user.convention.Constants.CacheConstants;
import com.wuzhipeng.heart.user.convention.Constants.LockRedission;
import com.wuzhipeng.heart.user.convention.errorcode.BaseErrorCode;
import com.wuzhipeng.heart.user.convention.exception.ClientException;
import com.wuzhipeng.heart.user.dao.entity.Therapist;
import com.wuzhipeng.heart.user.dao.entity.Therapistdata;
import com.wuzhipeng.heart.user.dao.mapper.TherapistdataMapper;
import com.wuzhipeng.heart.user.dto.request.TherapistInfoDTO;
import com.wuzhipeng.heart.user.dto.request.TherapistsDTO;
import com.wuzhipeng.heart.user.dto.request.registerDTO;
import com.wuzhipeng.heart.user.service.ITherapistdataService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wuzhipeng
 * @since 2024-12-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TherapistdataServiceImpl extends ServiceImpl<TherapistdataMapper, Therapistdata> implements ITherapistdataService {

    private final StringRedisTemplate stringRedisTemplate;
    private final RedissonClient redissonClient;
    @Override
    public TherapistInfoDTO getTherapistProfile() {

        String phone = UserContext.getPhone();
        if(stringRedisTemplate.hasKey(CacheConstants.THERAPISTER_DATA_CACHE+phone))
        {
            String json = stringRedisTemplate.opsForValue().get(CacheConstants.THERAPISTER_DATA_CACHE+UserContext.getPhone());
            TherapistInfoDTO therapistInfoDTO = JSONUtil.toBean(json, TherapistInfoDTO.class);
            return therapistInfoDTO;
        }
        LambdaQueryWrapper<Therapistdata> wrapper = Wrappers.lambdaQuery(Therapistdata.class)
                .eq(Therapistdata::getMobileNumber, phone);
        Therapistdata therapist = baseMapper.selectOne(wrapper);
        if(therapist == null)
            throw new ClientException(BaseErrorCode.USER_NOT_FOUND);
        TherapistInfoDTO therapistInfoDTO = BeanUtil.copyProperties(therapist, TherapistInfoDTO.class);
        therapistInfoDTO.setQualification(therapist.getQualificationCertificate());
        therapistInfoDTO.setExperience(therapist.getYearsOfExperience().toString());
        List<String> fields = new ArrayList<>();
        String[] split = therapist.getSpecialtyArea().split(",");
        for (String s : split) {
            fields.add(s.trim());
        }
        therapistInfoDTO.setFields(fields);
        therapistInfoDTO.setBio(therapist.getPersonalBio());
        therapistInfoDTO.setExpertise(therapist.getProfessionalStrengths());
        therapistInfoDTO.setPhone(therapist.getMobileNumber());
        therapistInfoDTO.setEmail(therapist.getEmail());
        stringRedisTemplate.opsForValue().set(CacheConstants.THERAPISTER_DATA_CACHE+phone, JSONUtil.toJsonStr(therapistInfoDTO), 60*60, TimeUnit.SECONDS);
        return therapistInfoDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTherapistProfile(TherapistInfoDTO therapistInfoDTO) {
        Therapistdata therapistdata = BeanUtil.copyProperties(therapistInfoDTO, Therapistdata.class);
        therapistdata.setQualificationCertificate(therapistInfoDTO.getQualification());
        String experience = therapistInfoDTO.getExperience();
        String year = experience.replace("年", "");
        therapistdata.setYearsOfExperience(Integer.parseInt(year));
        List<String> fields = therapistInfoDTO.getFields();
        StringBuilder field= new StringBuilder();
        for (String s : fields) {
            field.append(s.trim()).append(",");
        }
        therapistdata.setSpecialtyArea(field.toString());
        therapistdata.setPersonalBio(therapistInfoDTO.getBio());
        therapistdata.setProfessionalStrengths(therapistInfoDTO.getExpertise());
        therapistdata.setMobileNumber(therapistInfoDTO.getPhone());
        therapistdata.setEmail(therapistInfoDTO.getEmail());
        LambdaUpdateWrapper<Therapistdata> wrapper = Wrappers.lambdaUpdate(Therapistdata.class)
               .eq(Therapistdata::getMobileNumber, UserContext.getPhone());
        stringRedisTemplate.delete(CacheConstants.THERAPISTER_DATA_CACHE+UserContext.getPhone());
        stringRedisTemplate.opsForValue().set(CacheConstants.THERAPISTER_DATA_CACHE+UserContext.getPhone(), JSONUtil.toJsonStr(therapistInfoDTO), 60*60, TimeUnit.SECONDS);
        stringRedisTemplate.delete(CacheConstants.THERAPISTER_DATA_CACHE_LISTS);
        baseMapper.update(therapistdata, wrapper);
    }

    @Override
    public List<TherapistsDTO> getTherapists() {
        if(stringRedisTemplate.hasKey(CacheConstants.THERAPISTER_DATA_CACHE_LISTS))
        {
            String json = stringRedisTemplate.opsForValue().get(CacheConstants.THERAPISTER_DATA_CACHE_LISTS);
            List<TherapistsDTO> therapistsDTOList = JSONUtil.toList(json, TherapistsDTO.class);
            return therapistsDTOList;
        }
        RLock lock = redissonClient.getLock(LockRedission.LOCK_THERAISTDATA_KEY);
        try{
            lock.lock();
            if(stringRedisTemplate.hasKey(CacheConstants.THERAPISTER_DATA_CACHE_LISTS))
            {
                String json = stringRedisTemplate.opsForValue().get(CacheConstants.THERAPISTER_DATA_CACHE_LISTS);
                List<TherapistsDTO> therapistsDTOList = JSONUtil.toList(json, TherapistsDTO.class);
                return therapistsDTOList;
            }
            List<Therapistdata> therapists = baseMapper.selectList(Wrappers.emptyWrapper());
            log.info("therapists:{}", therapists);
            List<TherapistsDTO> therapistsDTOList = new ArrayList<>();
            for (Therapistdata therapist : therapists)
            {
                TherapistsDTO therapistsDTO=TherapistsDTO.builder()
                        .name(therapist.getName())
                        .id(RandomUtil.randomInt(0,10000000))
                        .title(Optional.ofNullable(therapist.getTitle()).orElse("无职称"))
                        .gender("男")
                        .qualification(Optional.ofNullable(therapist.getQualificationCertificate()).orElse("无资质证书"))
                        .experience(Optional.ofNullable(therapist.getYearsOfExperience()).orElse(0).toString())
                        .fields(Optional.ofNullable(therapist.getSpecialtyArea()).orElse("未填写领域"))
                        .bio(Optional.ofNullable(therapist.getPersonalBio()).orElse("无个人简介"))
                        .rating(RandomUtil.randomDouble(4.0,5.0))
                        .consultations(RandomUtil.randomInt(0,1000))
                        .phone(therapist.getMobileNumber())
                        .build();
                therapistsDTOList.add(therapistsDTO);
            }
            stringRedisTemplate.opsForValue().set(CacheConstants.THERAPISTER_DATA_CACHE_LISTS, JSONUtil.toJsonStr(therapistsDTOList), 60, TimeUnit.SECONDS);
            return therapistsDTOList;
        }
        finally {
            lock.unlock();
        }
    }

    /**
     * 注册咨询师详细信息
     * @param registerDTO
     */
    @Override
    public void registerTherapistdata(registerDTO registerDTO) {
        Therapistdata therapistdata = Therapistdata.builder()
               .mobileNumber(registerDTO.getPhone())
                .name(registerDTO.getName()).build();
        baseMapper.insert(therapistdata);
        stringRedisTemplate.delete(CacheConstants.THERAPISTER_DATA_CACHE_LISTS);
        return;
    }
}
